package com.hzw.saas.service.rss.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.rss.IJournalArticleService;
import com.hzw.saas.api.rss.ILibraryCatalogService;
import com.hzw.saas.api.rss.ILibraryService;
import com.hzw.saas.api.rss.bo.LibraryBO;
import com.hzw.saas.api.rss.query.JournalArticleFavQuery;
import com.hzw.saas.api.storage.IResourceFileService;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.config.util.PageUtils;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.service.rss.mapper.LibraryMapper;
import com.hzw.saas.service.rss.model.Library;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Service("libraryService")
public class LibraryServiceImpl extends ServiceImpl<LibraryMapper, Library> implements ILibraryService, IService<Library> {

    @Resource(name = "libraryCatalogServiceImpl")
    private ILibraryCatalogService libraryTreeService;
    @Resource(name = "journalArticleService")
    private IJournalArticleService journalArticleService;
    @Resource
    private IResourceFileService resourceFileService;

    @Override
    public LibraryBO addArticle(LibraryBO libraryBO) {
        if (null == libraryBO) {
            return null;
        }
        libraryTreeService.confirmLibraryCatalog(libraryBO.getLibraryCatalogId());
        if (StrUtil.isBlank(libraryBO.getPid())) {
            libraryBO.setPid(SnowFlakeUtil.nextIdStr());
        }
        dealLibraryAuthors(libraryBO);
        Library library = MapperUtil.nf().map(libraryBO, Library.class);

        String resourceMd5 = libraryBO.getResourceMd5();
        AssertUtil.assertThrow("添加失败，文献资源已存在", StrUtil.isNotBlank(resourceMd5) &&
            StrUtil.isNotBlank(libraryBO.getCreatorId()) &&
            this.existLibrary(libraryBO.getCreatorId(), resourceMd5));

        this.save(library);
        return MapperUtil.nf().map(library, LibraryBO.class);
    }

    @Override
    public void deleteArticle(String pid) {
        if (StrUtil.isBlank(pid)) {
            return;
        }
        removeResource(pid);
        removeById(pid);
    }


    @Override
    public void deleteBatch(List<String> pids) {
        if (CollUtil.isEmpty(pids)) {
            return;
        }
        pids.forEach(this::removeResource);
        this.removeByIds(pids);
    }

    private void removeResource(String pid) {
        Library library = this.getById(pid);
        if (Objects.isNull(library)) {
            return;
        }
        Integer type = library.getType();
        if (Objects.equals(type, 0)) {
            // 上传
            // TODO IResourceFileService 接口调整
            resourceFileService.deleteFile(library.getDownloadUrl());
        } else if (Objects.equals(type, 1)) {
            // 普通
            // 取消收藏文献
            JournalArticleFavQuery articleFavQuery = new JournalArticleFavQuery();
            articleFavQuery.setArticleId(library.getPid());
            articleFavQuery.setFav(0);
            articleFavQuery.setLibraryCatalogId("1");
            articleFavQuery.setUserId(library.getCreatorId());
            journalArticleService.collectArticle(articleFavQuery);
        }
    }

    @Override
    public void updateArticle(LibraryBO libraryBO) {
        if (Objects.isNull(libraryBO) || StrUtil.isBlank(libraryBO.getPid())) {
            return;
        }
        List<Library> list = this.lambdaQuery().eq(Library::getCreatorId, libraryBO.getCreatorId())
            .eq(Library::getArticleId, libraryBO.getPid())
            .list();
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        libraryTreeService.confirmLibraryCatalog(libraryBO.getLibraryCatalogId());
        libraryBO.setPid(list.get(0).getPid());
        libraryBO.setArticleId(list.get(0).getArticleId());
        dealLibraryAuthors(libraryBO);
        updateById(MapperUtil.nf().map(libraryBO, Library.class));
    }

    /**
     * 处理作者字段
     */
    private void dealLibraryAuthors(LibraryBO libraryBO) {
        List<String> authors = libraryBO.getAuthors();
        if (CollUtil.isNotEmpty(authors)) {
            String author = libraryBO.getAuthor();
            libraryBO.setAuthor(authors.stream().distinct().reduce(StrUtil.isBlank(author) ? "" : author, (cur, next) -> {
                if (StrUtil.isBlank(cur)) {
                    return next;
                }
                return cur.concat(StrUtil.COMMA).concat(next);
            }));
        }
    }

    @Override
    public boolean hasArticle(String libraryCatalogId) {
        if (StrUtil.isNotBlank(libraryCatalogId)) {
            return this.lambdaQuery().eq(Library::getLibraryCatalogId, libraryCatalogId).count() > 0;
        }
        return false;
    }

    @Override
    public IPage<LibraryBO> list(PageParam pageParam, String userId, String libraryCatalogId, Integer type) {
        Page<Library> page = this.lambdaQuery()
            .eq(Library::getCreatorId, userId)
            .eq(StrUtil.isNotBlank(libraryCatalogId), Library::getLibraryCatalogId, libraryCatalogId)
            .eq(Objects.nonNull(type), Library::getType, type)
            .page(pageParam.convert());

        return PageUtils.convert(page, LibraryBO.class);
    }

    @Override
    public int libraryCount(String userId, String catalogId) {
        return this.lambdaQuery()
            .eq(Library::getCreatorId, userId)
            .eq(Library::getLibraryCatalogId, catalogId)
            .count();
    }

    @Override
    public List<String> filterArticleFileIds(List<String> fileIds) {
        if (CollUtil.isEmpty(fileIds)) {
            return new ArrayList<>();
        }
        List<Library> list = super.lambdaQuery()
            .select(Library::getDownloadUrl)
            .in(Library::getDownloadUrl, fileIds)
            .list();
        return list.stream().map(Library::getDownloadUrl).collect(Collectors.toList());
    }

    @Override
    public boolean existLibrary(String userId, String resourceMd5) {
        if (StrUtil.isBlank(userId) || StrUtil.isBlank(resourceMd5)) {
            return false;
        }
        return this.lambdaQuery()
            .eq(Library::getCreatorId, userId)
            .eq(Library::getResourceMd5, resourceMd5).count() > 0;
    }

    public LibraryBO getLibraryByResourceMd5(String userId, String resourceMd5) {
        if (StrUtil.isBlank(userId) || StrUtil.isBlank(resourceMd5)) {
            return null;
        }
        List<Library> libraries = this.lambdaQuery()
            .eq(Library::getCreatorId, userId)
            .eq(Library::getResourceMd5, resourceMd5).list();
        return CollectionUtil.isNotEmpty(libraries) ? MapperUtil.nf().map(libraries.get(0), LibraryBO.class) : null;
    }

    @Override
    public LibraryBO getByPid(String pid) {
        Library byId = this.getById(pid);
        return MapperUtil.nf().map(byId,LibraryBO.class);
    }

    @Override
    public List<LibraryBO> getAriticleIds(List<String> collect) {

        if (CollectionUtil.isEmpty(collect)){
            return Collections.emptyList();
        }
        List<Library> list = this.lambdaQuery().in(Library::getArticleId, collect).list();
        return MapperUtil.nf().mapAsList(list,LibraryBO.class);
    }

    @Override
    public  List<LibraryBO> findAll() {
        List<Library> list = this.lambdaQuery().list();
        return MapperUtil.nf().mapAsList(list,LibraryBO.class);
    }

    @Override
    public void updateAll(List<LibraryBO> collect) {
        if (CollectionUtil.isEmpty(collect)){
            return;
        }
        List<Library> libraries = MapperUtil.nf().mapAsList(collect, Library.class);
        updateBatchById(libraries);
    }

    @Override
    public List<LibraryBO> getByArticleIds(List<String> pids) {
        if (CollectionUtil.isEmpty(pids)){
            return Collections.emptyList();
        }
        List<Library> list = this.lambdaQuery().in(Library::getArticleId, pids).list();
        return MapperUtil.nt().mapAsList(list,LibraryBO.class);

    }
}
